<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    .box{width: 200px;height: 40px;line-height: 40px;margin: 0 auto;text-indent: 4px;}
    .box span{display: block;width: 198px;height: 38px;border: solid 1px #666;position: relative;}
    .box span em{border-left: solid 5px transparent;border-right: solid 5px transparent;border-top: solid 5px #000;position: absolute;right: 10px;bottom:0;top:0;margin: auto 0;width: 0;height: 0;}
    .box .list{margin: 0;padding: 0;list-style: none;border: solid 1px #666;border-top: none;display: none;}
    .box .list li{position: relative;}
    .box .list li.hover{background: #55f;color: #fff;}
    .box .list li.active::after{content: "√";position: absolute;right: 10px;top:0;bottom:0;margin: auto 0;}
    i, em{font-style: normal;}
  </style>
</head>
<body>
  <select>
    <option>北京</option>
    <option>上海</option>
    <option selected>广州</option>
    <option>深圳</option>
    <option>杭州</option>
    <option>南京</option>
    <option>合肥</option>
  </select>

  <div class="box">
    <span><i></i> <em></em> </span>
    <ul class="list">
      <li>北京</li>
      <li>上海</li>
      <li>广州</li>
      <li>深圳</li>
      <li class="active">杭州</li>
      <li>南京</li>
      <li>合肥</li>
    </ul>
  </div>
</body>
<script>
  // 1. 选择元素
  var spanEle = $(".box span");
  var iEle = $(".box span i");
  var emEle = $(".box span em");
  var list = $(".box .list");
  var li = list.children;
  // 4. 记录当前下拉菜单的显示状态：true为显示，false为隐藏
  var isShow = false;

  // 6. 获取默认选中项的索引
  var index = 0;
  for(var i=0; i<li.length; i++){
    if(li[i].className.indexOf("active") !== -1){
      index = i;
      break;
    }
  }
  // 7. 根据默认选中项的索引，设置显示区域的内容
  iEle.innerText = li[index].innerText;

  // 2. 点击容器显示
  spanEle.onclick = function(eve){
    var e = eve||window.event;
    e.stopPropagation();
    // 5. 判断当前显示状态，决定显示或隐藏
    if(isShow){
      list.style.display = "none";
      isShow = false;
    }else{
      list.style.display = "block";
      isShow = true;
    }
  }
  // 3. 点击空白隐藏
  document.onclick = function(){
    list.style.display = "none";
    isShow = false;
  }

  // 8. 给所有li添加鼠标进入，鼠标离开，点击事件
  for(var i=0;i<li.length;i++){
    // 14. 给每个li绑定索引
    li[i].index = i;
    li[i].onmouseover = function(){
      // 9. 鼠标进入添加高亮样式
      this.classList.add("hover");
    }
    li[i].onmouseout = function(){
      // 10. 鼠标离开删除高亮样式
      this.classList.remove("hover");
    }
    li[i].onclick = function(){
      // 13. 删除上一个选中标志样式
      li[index].classList.remove("active");
      // 11. 鼠标点击，将当前项内容设置到显示区域
      iEle.innerText = this.innerText;
      // 12. 添加选中标志样式
      this.classList.add("active");
      // 15. 将本次点击的选项索引设置给默认索引，以备下次删除
      index = this.index;
    }
  }

  // 17. 键盘控制高亮项的默认索引
  var keyIndex;
  // 16. 添加键盘事件，上，下，回车
  document.onkeydown = function(eve){
    var e = eve || window.event;
    var code = e.keyCode || e.which;
    // 上键
    if(code === 38){
      // 18. 第一次按上键
      if(keyIndex === undefined){
        // 键盘的索引从最后一项开始
        keyIndex = li.length-1;
      }else
      // 19. 按上键到终点时
      if(keyIndex === 0){
        // 一直设置为终点值
        keyIndex = 0;
      }else{
        // 21. 清除之前索引的高亮样式
        li[keyIndex].classList.remove("hover");
        // 20. 既没到终点，也不是第一个按下，索引--
        keyIndex--;
      }
      // 22. 给当前计算之后的索引添加高亮样式
      li[keyIndex].classList.add("hover");
    }

    if(code === 40){
      if(keyIndex === undefined){
        keyIndex = 0;
      }else if(keyIndex === li.length-1){
        keyIndex = li.length-1;
      }else{
        li[keyIndex].classList.remove("hover");
        keyIndex++;
      }
      li[keyIndex].classList.add("hover");
    }

    // 回车键
    if(code === 13){
      // 23. 设置高亮项的内容到显示区域
      iEle.innerText = li[keyIndex].innerText;
      // 24. 删除之前选中项的标志
      li[index].classList.remove("active");
      // 25. 给当前选中项添加标志
      li[keyIndex].classList.add("active");
      // 隐藏下拉菜单
      list.style.display = "none";
      // 更新状态
      isShow = false;
      // 26. 将本次选中项的索引设置给默认索引，以备下次删除
      index = keyIndex;
    }
  }




  // 选择器封装
  function $(s){
    return document.querySelector(s);
  }


</script>
</html>